#include <thread>
#include <iostream>
#include "igslib_iutil.h"
#include "igslib_iserial_manager.h"

namespace igslib
{
    namespace serial_manager_sample
    {
        /*!
         * This sample demostrates how IUart component send 3 byte.
         * Runtime will display what byte would be sent.
         */
        static void UartSend()
        {
            ISerialManager* srm = GetSerialManagerInstance();
            IUart* uart = srm->NewM01Uart();
            IUart::DeviceNumber dn = IUart::ttyS1;
            //IUart::DeviceNumber dn = IUart::ttyXRUSB0;
            uart->SetBaudRate(115200);
            uart->SetDataBits(IUart::data_8bits);
            //uart->SetParityMode(IUart::pm_odd);
            //uart->SetStopBits(IUart::stop_2bits);
            bool odr = uart->Open(dn); // open device result
            std::cout << "Open device[" << dn << "]: " << odr << std::endl;

            char data[] = "abc";
            int send_rtn = uart->Send(data,sizeof(data));
            printf("%s/send> rtn=%d,data=",__func__,send_rtn);
            for ( int i = 0 ; i < sizeof(data) ; ++i )
            {
                printf("%02x ",data[i]);
            }
            printf("\n");

            uart->Close();
            getchar();
            exit(EXIT_SUCCESS);
        }
        /*!
         * This sample demostrates how IUart component receive data.
         * Runtime will display what byte would be received.
         */
        static void UartReceive()
        {
            ISerialManager* srm = GetSerialManagerInstance();
            IUart* uart = srm->NewM01Uart();
            IUart::DeviceNumber dn = IUart::ttyS1;
            //IUart::DeviceNumber dn = IUart::ttyXRUSB3;
            uart->SetBaudRate(115200);
            uart->SetDataBits(IUart::data_7bits);
            uart->SetParityMode(IUart::pm_odd);
            uart->SetStopBits(IUart::stop_2bits);
            bool odr = uart->Open(dn); // open device result
            std::cout << "Open device[" << dn << "]: " << odr << std::endl;
            std::cout << "Press [esc] to quit." << std::endl;

            while(util::KbHit()!=27)
            {
                char data[256] = {0};
                int length = uart->Receive(data,sizeof(data));
                if (length > 0)
                {
                    for ( int i = 0 ; i < length ; ++i )
                    {
                        printf("%02x,",data[i]);
                    }
                    printf("\n");
                    break;
                }
                util::SleepMSTime(16);
            }
            uart->Close();
            exit(EXIT_SUCCESS);
        }

        static void UartSend9bit()
        {
            ISerialManager* srm = GetSerialManagerInstance();

            //IUart* uart = srm->NewM01Uart();
            IUart9bit* uart = srm->NewM01Uart9bit();
            IUart::DeviceNumber dn = IUart::ttyS1;
            //IUart::DeviceNumber dn = IUart::ttyXRUSB0;
            uart->SetBaudRate(115200);
            //uart->SetDataBits(IUart::data_8bits);
            uart->SetDataBits(IUart::data_9bits);
            //uart->SetParityMode(IUart::pm_odd);
            //uart->SetStopBits(IUart::stop_2bits);
            bool odr = uart->Open(dn); // open device result
            std::cout << "Open device[" << dn << "]: " << odr << std::endl;

            //char data[] = {0x12,0x34,0x56,0x78};
            //short char2short[5] = {0};
            //char data[] = {0x12,0x34,0x56,0x78};
            short data [] = {0x0155,0x0055};
            // for(int i=0; i<5; i++)
            // {
            //    char2short[i] = 0x00 << 8| data[i];
            //    printf("char2short  %d : %04x  \n",i,char2short[i]);
            // }
            //int data[] = {0x1234,0x789a,0x4567,0xffff};

            //int send_rtn = uart->Send((char*)data,sizeof(data));
            int send_rtn = uart->Send(data,sizeof(data));
            //int send_rtn = uart->Send(data,10);

            printf("%s/send> rtn=%d,data=",__func__,send_rtn);
            for ( int i = 0 ; i < sizeof(data) ; ++i )
            {
                printf("%04x ",data[i]);
            }
            printf("\n");

            uart->Close();
            getchar();
            exit(EXIT_SUCCESS);
        }

        static void UartReceive9bit()
        {
            ISerialManager* srm = GetSerialManagerInstance();

            //IUart* uart = srm->NewM01Uart();
            IUart9bit* uart = srm->NewM01Uart9bit();
            //IUart::DeviceNumber dn = IUart::ttyS1;

            IUart::DeviceNumber dn = IUart::ttyXRUSB3;
            uart->SetBaudRate(115200);
            //uart->SetDataBits(IUart::data_8bits);
            uart->SetDataBits(IUart::data_9bits);
            //uart->SetParityMode(IUart::pm_odd);
            //uart->SetStopBits(IUart::stop_2bits);
            bool odr = uart->Open(dn); // open device result
            std::cout << "Open device[" << dn << "]: " << odr << std::endl;
            std::cout << "Press [esc] to quit." << std::endl;

            while(util::KbHit()!=27)
            {
                //char data[256] = {0};
                short data[256]={0};
                //int data[512] = {0};
                int length = uart->Receive(data,sizeof(data));
                if (length > 0)
                {
                    for ( int i = 0 ; i < length ; ++i )
                    {
                        printf("%04x,",data[i]);
                    }
                    printf("\n");
                    break;
                }
                util::SleepMSTime(16);
            }
            uart->Close();
            exit(EXIT_SUCCESS);
        }

        static void SpiRW()
        {
            const int len = 256;
            char txbuf[len] = {0};
            char rxbuf[len] = {0};
            ISerialManager* srm = GetSerialManagerInstance();
            if (srm == NULL)
            {
                std::stringstream ss;
                ss << __func__ << "/GetSerialManagerInstance()>";
                throw_igslib_exception(ss.str());
            }
            //ISpi* spi = srm->NewM01Spi();
            ISpi* spi = srm->New_ProjMCU_spi("DragonBallRace");
            if (spi == NULL)
            {
                std::stringstream ss;
                ss << __func__ << "/NewM01Spi()>";
                throw_igslib_exception(ss.str());
            }
            spi->SetWorkingFrequency(10000000);
            bool open_result = spi->Open(ISpi::cs4);
            if (open_result == false)
            {
                std::stringstream ss;
                ss << __func__ << "/spi->Open()>";
                throw_igslib_exception(ss.str());
            }

            for( int idx = 0; idx<1000; idx++)
            {
                for ( int i = 5 ; i < len ; ++i )
                {
                    txbuf[0]=idx;  //fix contain
                    txbuf[1]=idx+1;
                    txbuf[2]=idx+2;
                    txbuf[3]=0x55;
                    txbuf[4]=0xAA;   
                    txbuf[i] =i;   //sequence
                }
                bool transfer_result = spi->FullDuplexReadWrite(txbuf,rxbuf,len);
                if (transfer_result == false)
                {
                    std::stringstream ss;
                    ss << __func__ << "spi->FullDuplexReadWrite()";
                    throw_igslib_exception(ss.str());
                }
                printf("%s/rx_buf=",__func__);
                for ( int i = 0 ; i < len ; ++i )
                    printf("%02x ",rxbuf[i]);
                printf("\n");
            }
            spi->Close();
            exit(EXIT_SUCCESS);
        }
    };
};
